package com.eric.seo.serp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.log4j.PropertyConfigurator;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.eric.downloader.BaiduSERPDownloader;
import com.eric.reporting.ArrayMap;

/**
 * 查询百度SERP 输入文件格式：一行一个关键词 输出json格式结果
 * 
 * @author eric
 */
public class BaiduSERPAnalyzer implements Runnable {

	private ArrayMap<String, Object> result = new ArrayMap<String, Object>();

	public static LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();

	private String kw;

	private static PrintWriter pw;

	Logger logger;

	protected static AtomicInteger threadNum = new AtomicInteger(0);

	public static void main(String[] args) throws IOException {
		File file_in = new File(args[0]);
		BufferedReader br;
		try {
			br = new BufferedReader(new FileReader(file_in));
			String line;
			while ((line = br.readLine()) != null && !line.equals("")) {
				queue.add(line);
			}
			br.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		File file_out = new File(file_in.getAbsolutePath() + ".serp");
		try {
			pw = new PrintWriter(new FileWriter(file_out), true);
		} catch (IOException e) {
			e.printStackTrace();
		}

		ExecutorService exe = Executors.newCachedThreadPool();

		for (int i = 0; i < 2; i++) {
			exe.execute(new BaiduSERPAnalyzer());
		}

		exe.shutdown();
	}

	/**
	 * 构造函数 读取关键词列表到阻塞队列<br>
	 * 构造报告输出的BufferedWriter
	 * 
	 * @param kwListLoc
	 */
	public BaiduSERPAnalyzer() {
		logger = LoggerFactory.getLogger(BaiduSERPAnalyzer.class);
		PropertyConfigurator.configure("log4j.properties");
	}

	@Override
	public void run() {
		threadNum.incrementAndGet();
		while (true) {
			String kw = poll();
			analyze(kw);
			saveAndNew();
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			if (threadNum.get() == 0 || queue.size() == 0) {
				break;
			}
		}
		threadNum.decrementAndGet();
	}

	synchronized String poll() {
		return queue.poll();
	}

	public ArrayMap<String, Object> analyze(String kw) {
		this.kw = kw;
		BaiduSERPDownloader bd = new BaiduSERPDownloader(kw).get();
		result.put("kw", kw);
		result.put("top10", top10(bd.document()));
		result.put("rec", getRecKw(bd.document()).get("rec"));

		return result;
	}

	/**
	 * 根据SERP解析推荐关键词
	 * 
	 * @param doc
	 *            Document
	 * @return json格式的推荐关键词list
	 */
	public JSONObject getRecKw(Document doc) {
		JSONObject json = new JSONObject();
		List<String> list = new ArrayList<>();
		String[] a = doc.getElementsByAttributeValue("id", "rs").select("th").text().split(" ");
		for (int i = 0; i < a.length; i++) {
			list.add(a[i]);
		}
		json.put("rec", list);
		return json;
	}

	/**
	 * 独立使用，根据SERP解析推荐关键词
	 * 
	 * @param kw
	 *            String格式的关键词
	 * @return json格式的推荐关键词list
	 */
	public JSONObject getRecKw(String kw) {
		BaiduSERPDownloader bd = new BaiduSERPDownloader(kw).get();
		return getRecKw(bd.document());
	}

	/**
	 * 返回百度前十的url,title和description Result Format:<br>
	 * "url":url<br>
	 * "title":title<br>
	 * "description":description
	 * 
	 * @return JSONObject
	 * @param doc
	 *            Downloaded Document
	 */
	public JSONObject top10(Document doc) {
		Elements elements = doc.getElementsByAttributeValueStarting("class", "result");
		
		JSONObject top10J = new JSONObject();

		ExecutorService exe = Executors.newCachedThreadPool();
		List<Future<JSONObject>> futures = new ArrayList<>();
		
		for (int i = 1; i <= 10; i++) {
			futures.add(exe.submit(new Top10(elements, i, kw)));
		}
		
		for (Future<JSONObject> f : futures) {
			try {
				top10J.putAll(f.get());
			} catch (NullPointerException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
		}
		
		exe.shutdown();
		
		return top10J;
	}

	public ArrayMap<String, Object> result() {
		return this.result;
	}

	synchronized public void saveAndNew() {
		try {
			pw.println(result().json().toJSONString()
					.replaceAll("\\\\", "")
					.replace("\"{", "{")
					.replace("}\"", "}"));//多线程的FUTURE会返回一些奇怪东西，待处理
			result = new ArrayMap<>();
		} catch (ArrayIndexOutOfBoundsException e) {
			
		}
	}
	
}

